package com.suns.service;

import com.google.common.base.Preconditions;
import com.suns.dao.SysDeptMapper;
import com.suns.exception.ParamException;
import com.suns.model.SysDept;
import com.suns.param.DeptParam;
import com.suns.util.BeanValidator;
import com.suns.util.LevelUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Service
public class SysDeptService {
    @Resource
    private SysDeptMapper sysDeptMapper;//警告

    // updateWithChild 加入事物的注解 保证其一致性（要么都成功，要么都失败）
    @Transactional
    private void updateWithChild(SysDept beforeDept, SysDept afterDept) {

        // 判断是否更新子部门
        // 分别获取更改前后的level
        String newLevelPrefix = afterDept.getLevel();// 0.1
        String oldLevelPrefix = beforeDept.getLevel();// 0.2

        // 判断leve是否更改，如果更改，子部门也许更改
        if (!newLevelPrefix.equals(oldLevelPrefix)) {
            // 取出当前部门的子部门
            List<SysDept> deptList = sysDeptMapper.getChildDeptListByLevel(beforeDept.getLevel());

            // 当前子部门不为空才需处理
            if (CollectionUtils.isNotEmpty(deptList)) {
                // 遍历子部门集合内的单个部门
                for (SysDept dept : deptList) {
                    // 计算新的level
                    String level = dept.getLevel();// 0.2.1
                    // (0.2.1).indexOf(0.2) == 0
                    if (level.indexOf(oldLevelPrefix) == 0) {
                        // 0.1 + (0.2.1).subString((0.2).length)=1  -->0.1.1
                        level = newLevelPrefix + level.substring(oldLevelPrefix.length());
                        // 更新dept内的level
                        dept.setLevel(level);
                    }

                }
                // 批量更新子部门 level
                sysDeptMapper.batchUpdateLevel(deptList);
            }
        }

        //更新本部门
        sysDeptMapper.updateByPrimaryKey(afterDept);
    }


    /**
     * 修改部门的方法
     * @param param
     */
    public void update(DeptParam param) {
        BeanValidator.check(param);

        // 获取更新前的部门数据 old
        SysDept beforeDept = sysDeptMapper.selectByPrimaryKey(param.getId());
        // 判断更新前的部门是否为空，为空则抛出异常
        Preconditions.checkNotNull(beforeDept, "待更新的部门不存在");

        // 待完善的方法 checkExist(,,,)
        if (checkExist(param.getParentId(), param.getName(), param.getId())) {
            throw new ParamException("同一层级下存在相同名称的部门");
        }
        // build更新后的数据
        SysDept afterDept = SysDept.builder().id(param.getId()).name(param.getName()).parentId(param.getParentId())
                .seq(param.getSeq()).remark(param.getRemark()).build();
        // 需计算level，使用自定义level工具类
        afterDept.setLevel(LevelUtil.calculateLevel(getLevel(param.getParentId()),param.getParentId()));
        afterDept.setOperator("system-update"); // TODO
        afterDept.setOperateIp("127.0.0.1"); // TODO
        afterDept.setOperateTime(new Date());

        //
        updateWithChild(beforeDept,afterDept);
    }

    /**
     * 获取本级别的level
     * @param deptId
     * @return
     */
    private String getLevel(Integer deptId){
        SysDept dept = sysDeptMapper.selectByPrimaryKey(deptId);
        if (dept == null) {
            return null;
        }
        return dept.getLevel();
    }

    /**
     * 检验信息是否已经重复(同一级下不能有名称重复的部门)    *****待完善****
     * @param parentId （父级部门id）
     * @param name （部门名称）
     * @param deptId (修改时,部门id)
     * @return
     */
    private boolean checkExist(Integer parentId, String name, Integer deptId) {

        return (sysDeptMapper.countByNameAndParentId(parentId, name, deptId)) > 0 ;
    }

    /**
     * 新增部门的方法
     * @param param
     */
    public void save(DeptParam param) {
        BeanValidator.check(param);
        // 待完善的方法 checkExist(,,,)
        if (checkExist(param.getParentId(), param.getName(), param.getId())) {
            throw new ParamException("同一层级下存在相同名称的部门");
        }

        // 组装当前部门
        SysDept dept=SysDept.builder().name(param.getName()).parentId(param.getParentId())
                .seq(param.getSeq()).remark(param.getRemark()).build();
        // 需计算level，使用自定义level工具类
        String parentLevel = getLevel(param.getParentId());
        dept.setLevel(LevelUtil.calculateLevel(parentLevel,param.getParentId()));
        dept.setOperator("system"); // TODO
        dept.setOperateIp("127.0.0.1"); // TODO
        dept.setOperateTime(new Date());

        sysDeptMapper.insertSelective(dept);
    }

}
